package com.sunnyday.excelexporttest;

import com.sun.management.OperatingSystemMXBean;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class PerformanceMonitor {
    private long wallStartTime;
    private long wallEndTime;

    private long memoryBefore;
    private long memoryAfter;

    private long threadCpuStartTime;
    private long threadCpuEndTime;

    private long processCpuStartTime;
    private long processCpuEndTime;

    private final OperatingSystemMXBean osBean;
    private final ThreadMXBean threadBean;

    public PerformanceMonitor() {
        osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
        threadBean = ManagementFactory.getThreadMXBean();
    }

    public void start() {
        // 尽量释放内存，防止影响内存统计
        System.gc();
        try {
            Thread.sleep(1000); // 等待GC完成
        } catch (InterruptedException ignored) {}

        wallStartTime = System.nanoTime();
        memoryBefore = getUsedMemory();

        threadCpuStartTime = getCurrentThreadCpuTime();
        processCpuStartTime = getProcessCpuTime();
    }

    public void end(String tag) {
        wallEndTime = System.nanoTime();
        memoryAfter = getUsedMemory();

        threadCpuEndTime = getCurrentThreadCpuTime();
        processCpuEndTime = getProcessCpuTime();

        long durationMs = (wallEndTime - wallStartTime) / 1_000_000;
        double threadCpuMs = (threadCpuEndTime - threadCpuStartTime) / 1_000_000.0;
        double processCpuMs = (processCpuEndTime - processCpuStartTime) / 1_000_000.0;
        double memoryMB = (memoryAfter - memoryBefore) / 1024.0 / 1024.0;

        int cpuCores = osBean.getAvailableProcessors();
        double cpuUsage = (wallEndTime > wallStartTime && cpuCores > 0)
                ? (processCpuEndTime - processCpuStartTime) * 100.0 / ((wallEndTime - wallStartTime) * cpuCores)
                : 0.0;

        System.out.printf("=== [%s] 导出性能统计 ===%n", tag);
        System.out.printf("耗时：%d ms%n", durationMs);
        System.out.printf("主线程 CPU 时间：%.2f ms%n", threadCpuMs);
        System.out.printf("进程总 CPU 时间：%.2f ms%n", processCpuMs);
        System.out.printf("CPU 占用率：%.2f%%%n", cpuUsage);
        System.out.printf("内存使用：%.2f MB%n", memoryMB);
        System.out.println("=============================");
    }

    private long getUsedMemory() {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }

    private long getCurrentThreadCpuTime() {
        return threadBean.isCurrentThreadCpuTimeSupported()
                ? threadBean.getCurrentThreadCpuTime()
                : 0L;
    }

    private long getProcessCpuTime() {
        return osBean.getProcessCpuTime();
    }
}
